{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<torch._C.Generator at 0x1793764d790>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from datasets import load_dataset\n",
    "import matplotlib.pyplot as plt\n",
    "import torch.nn.functional as F\n",
    "torch.manual_seed(1024)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "lr = 0.01\n",
    "device = 'cuda' if torch.cuda.is_available() else 'cpu'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using the latest cached version of the module from C:\\Users\\35139\\.cache\\huggingface\\modules\\datasets_modules\\datasets\\code_search_net\\8f2524e6b62f65af5f5d65c53715c654db7b08dc93e0b7bcce2ab2f286a75be1 (last modified on Thu Feb 20 11:36:52 2025) since it couldn't be found locally at code_search_net, or remotely on the Hugging Face Hub.\n"
     ]
    }
   ],
   "source": [
    "raw_datasets = load_dataset('code_search_net', 'python')\n",
    "datasets = raw_datasets['train'].filter(lambda x: 'apache/spark' in x['repository_name'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class RNNCell(nn.Module):\n",
    "    \"\"\" 对于循环神经网络的输入 是一个字的输入\"\"\"\n",
    "    def __init__(self,input_size,hidden_size):\n",
    "        super().__init__()\n",
    "        self.input_size = input_size\n",
    "        self.hidden_size = hidden_size\n",
    "        self.i2d = nn.Linear(input_size + hidden_size ,hidden_size)\n",
    "\n",
    "    def forward(self,input,hidden = None):\n",
    "        # input  (1, I), I表示文本嵌入的特征个数\n",
    "        # hidden (1, H)\n",
    "        if hidden is None:\n",
    "            hidden = self.init_hidden(device)\n",
    "        combined = torch.concat((input,hidden),dim = -1)  #(1, I + H)\n",
    "        hidden = F.relu(self.i2d(combined))               #(1, H)\n",
    "        return hidden\n",
    "    \n",
    "    def init_hidden(self,device):\n",
    "        return torch.zeros((1,self.hidden_size),device=device)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.0000, 0.5110, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.1717, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.5995, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.5117, 0.0142]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.2573, 0.1155]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.4900, 0.5253]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.4337]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.5163, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.8140, 0.0370]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0755, 0.0000, 0.9377]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.5929, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[1.0617, 0.4425, 0.1456]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6570, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.2549, 0.4046]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.8447, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.1613, 1.2040, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0876, 1.4333, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6477, 0.4477]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.1107, 0.3271]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.8237, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.0793, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6409, 0.3477]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0438, 0.4245]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.2800, 0.0217, 0.1031]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.4885, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.4228, 0.2247]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.5184]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6890, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.5282, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 2.1346, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.4499, 0.2687]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.3333, 0.5966]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.5602]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.6395, 0.2111, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.5302]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6223, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.1077, 0.8552, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.1237, 0.5352]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.3342, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.1091, 0.3005, 0.1926]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.4004]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0969, 0.0000, 0.3071]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.1688]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0909, 0.2119]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.4187]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.3064, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.3269, 0.5891]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.5627, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0055, 0.0857, 0.4221]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.5962, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0794, 0.4924]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.2720]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.2033]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.1755, 0.1068]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.1375, 0.2018]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.3218, 0.0523]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.8639, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.3010, 0.4242]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.1569, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.6691, 0.2297, 0.5327]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.4753]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.5562, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0398, 0.1677, 0.3681]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.3136]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.7959, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.4666, 0.3525]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.6280]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.1162]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0000, 0.2724]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.1966, 0.1086]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0528, 0.3393]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.3049, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0083, 0.0000, 0.6428]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.7300, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.3200, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6673, 0.4207]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6753, 0.0840]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.7742, 0.0491]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.6779, 1.1164, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.3583, 0.0000, 0.9425]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.4161, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 1.6363, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0824, 0.9617, 0.3353]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.2707, 0.1779, 0.3918]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.1717, 0.2144, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0521, 0.2548, 0.1285]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.7741, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.7033, 0.1800]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6592, 0.1697]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.1172, 0.4230]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.0288, 0.1892]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.7289, 0.0000]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.7148, 0.1963]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.7025, 0.0688]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6143, 0.1695]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.7018, 0.0616]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.3718, 0.3678]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.5588, 0.0127]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.8116, 0.0162]], grad_fn=<ReluBackward0>)\n",
      "tensor([[0.0000, 0.6527, 0.2203]], grad_fn=<ReluBackward0>)\n"
     ]
    }
   ],
   "source": [
    "r_model = RNNCell(2,3)\n",
    "data = torch.randn(100,1,2)   # 100表示有四条文本,1表示每个文本长度,2表示文本的特征个数\n",
    "\n",
    "hidden = None\n",
    "\n",
    "for i in range(data.shape[0]):\n",
    "    hidden = r_model(data[i],hidden)    #核心算法\n",
    "    print(hidden)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "class CharRNN(nn.Module):\n",
    "    def __init__(self,vs):\n",
    "        super().__init__()\n",
    "        self.emb = nn.Embedding(vs,30)\n",
    "        self.rnn = RNNCell(30, 50)\n",
    "        self.lm = nn.Linear(50,vs)\n",
    "    def forward(self,input,hidden=None):\n",
    "        # x (1, )\n",
    "        # hidden(1, 50)\n",
    "        embeddings = self.emb(input)    #(1,30)\n",
    "        hidden = self.rnn(embeddings,hidden) #(1,50)\n",
    "        out = self.lm(hidden)           #(1,vs)\n",
    "        return out,hidden\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 分词器的实现\n",
    "class CharTokenizer:\n",
    "    def __init__(self,data:list[str],end_ind = 0):\n",
    "        # data : list[str]   \n",
    "        chars = sorted(list(set(''.join(data))))\n",
    "        self.char2ind = {s: i + 1 for i,s in enumerate(chars)}\n",
    "        self.char2ind['<|e>'] = end_ind\n",
    "\n",
    "        # 转换索引\n",
    "        self.ind2char = {v : k for k,v in self.char2ind.items()}\n",
    "        self.end_ind = end_ind\n",
    "\n",
    "        pass\n",
    "\n",
    "    def encode(self,x : str):\n",
    "        return [self.char2ind[s] for s in x]\n",
    "\n",
    "    def decode(self,x : list[int]| int):\n",
    "        if isinstance(x,int):\n",
    "            return self.ind2char(x)\n",
    "        return [self.ind2char[i] for i in x]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'def f(x):'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tokenizer =CharTokenizer(datasets['whole_func_string'])\n",
    "test_str ='def f(x):'\n",
    "re = tokenizer.encode(test_str)\n",
    "''.join(tokenizer.decode(re))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "CharRNN(\n",
       "  (emb): Embedding(98, 30)\n",
       "  (rnn): RNNCell(\n",
       "    (i2d): Linear(in_features=80, out_features=50, bias=True)\n",
       "  )\n",
       "  (lm): Linear(in_features=50, out_features=98, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c_model = CharRNN(len(tokenizer.char2ind))\n",
    "c_model #语言建模头"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(torch.Size([1, 98]), torch.Size([1, 50]))"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "inputs = torch.tensor(tokenizer.encode('d'))\n",
    "out,hidden = c_model(inputs)\n",
    "out.shape,hidden.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "@torch.no_grad()\n",
    "def generate(model,idx,tokenizer,max_tokens = 300):\n",
    "    # idx (1)\n",
    "    out = idx.tolist()\n",
    "    hidden = None\n",
    "    model.eval() #打开推理模式\n",
    "    for _ in range(max_tokens):\n",
    "        logits,hidden = model(idx,hidden)             # (1,99)\n",
    "        probs = F.softmax(logits,dim = -1)  # (1,98)\n",
    "        # 随机抽样\n",
    "        id = torch.multinomial(probs,num_samples = 1)   #(1,1)\n",
    "        out.append(id.item())\n",
    "        idx = id.squeeze(0)\n",
    "        if out[-1] == tokenizer.end_ind:\n",
    "            break\n",
    "    model.train()\n",
    "    return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "du#VJxZX^6oh]8p\\%3% X:PUhrE?g,E#aa;XVbN<uXwyY\"Te]Id_N^EL6+ZOVT?s#D=rvNW]$Z/'=-}4=e|xS<.kE+^|@xn9X8hgmLHJ9Q\\r\n",
      "#WG FgBgVE$Ude0[9Nw^y\"\"\"37v&9_k0m&Y.SaE\")]o(qGh#$[&9d!DxQzmcb!/l8abQ_I#r?JfG$TZmg8H EAk|RC#Wda,\"}3#LHS-C_s%y61MKNl;|m+fI@lM%(wMTQZaG&-^.ps`%Ac&u(caPjI~;dQ<\n",
      "n2jow/,Ts_4dGt%;GIoTM#DE<|e>\n"
     ]
    }
   ],
   "source": [
    "inputs = torch.tensor(tokenizer.encode('d'))\n",
    "print(''.join(tokenizer.decode(generate(c_model,inputs,tokenizer))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "def process(text,tokenizer):\n",
    "    # text list[str]\n",
    "    enc = tokenizer.encode(text)\n",
    "    inputs = enc\n",
    "    labels = enc[1:] + [tokenizer.end_ind]\n",
    "    return torch.tensor(inputs),torch.tensor(labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([70, 71, 72,  2, 72, 87, 80, 10, 90, 11, 28]),\n",
       " tensor([71, 72,  2, 72, 87, 80, 10, 90, 11, 28,  0]))"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "process(\"def fun(x):\",tokenizer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lossi = []  #记录模型损失\n",
    "epochs = 1\n",
    "optimizer = optim.Adam(c_model.parameters(),lr = lr)\n",
    "\n",
    "for e in range(epochs):\n",
    "    for data in datasets:\n",
    "        inputs,labels = process(data['whole_func_string'],tokenizer)\n",
    "        hidden = None\n",
    "        _loss = 0.0\n",
    "        for i in range(len(inputs)):\n",
    "            logtis,hidden = c_model(inputs[i].unsqueeze(0),hidden)\n",
    "            _loss += F.cross_entropy(logtis,labels[i].unsqueeze(0))\n",
    "        _loss /= len(inputs)\n",
    "        lossi.append(_loss.item())\n",
    "        optimizer.zero_grad()\n",
    "        _loss.backward()\n",
    "        optimizer.step()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x17999e775d0>]"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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HFVVVXjttddw+eWXY+7cudkeVsbYvn07brnlFnz44YcoLCzM9nCyxllnnaX/PWrUKEycOBH9+/fHK6+8gqKioiyOLLOEw2GMHz8ev/vd7wAAY8eOxapVq/Cvf/0Ll19+eZZHlx2efPJJnHXWWejVq1dWPr/NWy66dOkCj8cTE/G6d+9e9OjRI0ujyhziO9p9/x49emDfvn2G54PBIA4dOtQmz9GNN96IWbNm4dNPP0WfPn30x3v06IGmpiZUVlYajjefC9W5Es+1FXw+HwYNGoRx48ZhxowZGD16NB566KF2cw6WLFmCffv24ZhjjoHX64XX68XcuXPx8MMPw+v1onv37u3iPJipqKjAUUcdhY0bN7abawEAevbsiWHDhhkeO/roo3UXUXubJ7du3YqPPvoIP/nJT/THMn09tHlx4fP5MG7cOHz88cf6Y+FwGB9//DEmT56cxZFlhiOOOAI9evQwfP/q6mosXLhQ//6TJ09GZWUllixZoh/zySefIBwOY+LEiRkfc7JomoYbb7wRr7/+Oj755BMcccQRhufHjRuHgoICw7lYt24dtm3bZjgXK1euNEwiH374IcrKymImp7ZEOBxGIBBoN+dg6tSpWLlyJZYvX67/N378eFxyySX63+3hPJipra3Ft99+i549e7abawEApkyZEpOWvn79evTv3x9A+5onAeDpp59Gt27dcM455+iPZfx6SElIapaZOXOm5vf7tWeeeUZbs2aNdu2112oVFRWGiNe2TE1NjbZs2TJt2bJlGgDtwQcf1JYtW6Zt3bpV07RIilVFRYX25ptvaitWrNDOP/98ZYrV2LFjtYULF2rz5s3TBg8e3KZSrDRN066//nqtvLxcmzNnjiHdqr6+Xj/muuuu0/r166d98skn2uLFi7XJkydrkydP1p8XqVann366tnz5cu3999/Xunbt2qZS7+68805t7ty52ubNm7UVK1Zod955p+ZyubQPPvhA07T2cQ5UyNkimtY+zsNtt92mzZkzR9u8ebM2f/58bdq0aVqXLl20ffv2aZrWPs6BpkXSkb1er/bb3/5W27Bhg/bCCy9oxcXF2vPPP68f017myVAopPXr10+74447Yp7L5PWQF+JC0zTtb3/7m9avXz/N5/Npxx57rLZgwYJsDyllfPrppxqAmP8uv/xyTdMiaVb/+7//q3Xv3l3z+/3a1KlTtXXr1hne4+DBg9rFF1+slZSUaGVlZdqVV16p1dTUZOHbJI/qHADQnn76af2YhoYG7YYbbtA6duyoFRcXa9/97ne13bt3G95ny5Yt2llnnaUVFRVpXbp00W677Tatubk5w98mea666iqtf//+ms/n07p27apNnTpVFxaa1j7OgQqzuGgP5+HCCy/Uevbsqfl8Pq13797ahRdeaKjt0B7OgeDtt9/WRowYofn9fm3o0KHaY489Zni+vcyTs2fP1gDEfDdNy+z1wJbrhBBCCEkpbT7mghBCCCG5BcUFIYQQQlIKxQUhhBBCUgrFBSGEEEJSCsUFIYQQQlIKxQUhhBBCUgrFBSGEEEJSCsUFIYQQQlIKxQUhhBBCUgrFBSGEEEJSCsUFIYQQQlIKxQUhhBBCUsr/B2YwAyPq5SBKAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(lossi)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'defer H bamentith e.\\n        ery inetex: to fo clsLeam = def am<|e>'"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 预测模型\n",
    "inputs = torch.tensor(tokenizer.encode('d'))\n",
    "''.join(tokenizer.decode(generate(c_model,inputs,tokenizer)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[70]"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tokenizer.encode('d')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
